gsk: Recycle textures across frames
authorEmmanuele Bassi <ebassi@gnome.org>
Thu, 4 Aug 2016 11:37:54 +0000 (12:37 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Tue, 18 Oct 2016 10:49:11 +0000 (11:49 +0100)
We keep the textures used inside a frame around until the end of the
following frame; whenever we need a texture with the same size, and
it's not marked in use, then we just reuse the existing texture.

gsk/gskgldriver.c
gsk/gskgldriverprivate.h
gsk/gskglrenderer.c

index 52d8631df51be68ce3b63de9ecdd5ed7f5b83c05..443a0ad840ac93333bc7ed2472419bf2bab5e4ca 100644 (file)
@@ -14,6 +14,7 @@ typedef struct {
   GLuint min_filter;
   GLuint mag_filter;
   GArray *fbos;
+  gboolean in_use : 1;
 } Texture;
 
 typedef struct {
@@ -106,9 +107,14 @@ gsk_gl_driver_finalize (GObject *gobject)
 {
   GskGLDriver *self = GSK_GL_DRIVER (gobject);
 
+  gdk_gl_context_make_current (self->gl_context);
+
   g_clear_pointer (&self->textures, g_hash_table_unref);
   g_clear_pointer (&self->vaos, g_hash_table_unref);
 
+  if (self->gl_context == gdk_gl_context_get_current ())
+    gdk_gl_context_clear_current ();
+
   g_clear_object (&self->gl_context);
 
   G_OBJECT_CLASS (gsk_gl_driver_parent_class)->finalize (gobject);
@@ -232,6 +238,27 @@ gsk_gl_driver_end_frame (GskGLDriver *driver)
   driver->in_frame = FALSE;
 }
 
+void
+gsk_gl_driver_collect_textures (GskGLDriver *driver)
+{
+  GHashTableIter iter;
+  gpointer value_p = NULL;
+
+  g_return_if_fail (GSK_IS_GL_DRIVER (driver));
+  g_return_if_fail (!driver->in_frame);
+
+  g_hash_table_iter_init (&iter, driver->textures);
+  while (g_hash_table_iter_next (&iter, NULL, &value_p))
+    {
+      Texture *t = value_p;
+
+      if (t->in_use)
+        t->in_use = FALSE;
+      else
+        g_hash_table_iter_remove (&iter);
+    }
+}
+
 static Texture *
 gsk_gl_driver_get_texture (GskGLDriver *driver,
                            int          texture_id)
@@ -268,6 +295,26 @@ gsk_gl_driver_get_fbo (GskGLDriver *driver,
   return &g_array_index (t->fbos, Fbo, 0);
 }
 
+static Texture *
+find_texture_by_size (GHashTable *textures,
+                      int         width,
+                      int         height)
+{
+  GHashTableIter iter;
+  gpointer value_p = NULL;
+
+  g_hash_table_iter_init (&iter, textures);
+  while (g_hash_table_iter_next (&iter, NULL, &value_p))
+    {
+      Texture *t = value_p;
+
+      if (t->width == width && t->height == height)
+        return t;
+    }
+
+  return NULL;
+}
+
 int
 gsk_gl_driver_create_texture (GskGLDriver *driver,
                               int          width,
@@ -278,6 +325,13 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
 
   g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
 
+  t = find_texture_by_size (driver->textures, width, height);
+  if (t != NULL && !t->in_use)
+    {
+      t->in_use = TRUE;
+      return t->texture_id;
+    }
+
   glGenTextures (1, &texture_id);
 
   t = texture_new ();
@@ -286,6 +340,7 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
   t->height = height;
   t->min_filter = GL_NEAREST;
   t->mag_filter = GL_NEAREST;
+  t->in_use = TRUE;
   g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t);
 
   return t->texture_id;
index 30eaffa1fbd31b48f593193797675f8dfb0dcfe9..b69a387ca71db1503f1cc861874c73a2f0bb1794 100644 (file)
@@ -56,6 +56,8 @@ void            gsk_gl_driver_destroy_texture           (GskGLDriver     *driver
 void            gsk_gl_driver_destroy_vao               (GskGLDriver     *driver,
                                                          int              vao_id);
 
+void            gsk_gl_driver_collect_textures          (GskGLDriver     *driver);
+
 G_END_DECLS
 
 #endif /* __GSK_GL_DRIVER_PRIVATE_H__ */
index de6b2c3d22801bc698a86d3b12955af920dc7573..1e3dcd2e3d93abc94a664e84a71d3dfe3a1a557d 100644 (file)
@@ -798,7 +798,6 @@ static void
 render_item_clear (RenderItem    *item,
                    GskGLRenderer *self)
 {
-  gsk_gl_driver_destroy_texture (self->gl_driver, item->render_data.texture_id);
   gsk_gl_driver_destroy_vao (self->gl_driver, item->render_data.vao_id);
 }
 
@@ -820,6 +819,8 @@ gsk_gl_renderer_clear_tree (GskGLRenderer *self)
     }
 
   g_clear_pointer (&self->render_items, g_array_unref);
+
+  gsk_gl_driver_collect_textures (self->gl_driver);
 }
 
 static void